﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using WORD = System.UInt16;
using DWORD = System.UInt32;
using BYTE = System.Byte;
using ULONGLONG = System.UInt64;
using WCHAR = System.String;
using System.Reflection;
using System.Runtime.InteropServices;

namespace Pub
{
    /// <summary>
    /// pe结构解析
    /// </summary>
    public class CPE
    {

        public Int32 FILE_LENGTH = 0;                               //文件长度
        public byte[] FILE_ARRAY;

        public CPE()
        {
            DOS_HEADER.e_res = new WORD[4];
            DOS_HEADER.e_res2 = new WORD[10];
        }

        const int IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16;        //

        //DOS头
        public string[] DOS_HEADER_TXT = new string[] { "e_magic", "e_cblp", "e_cp", "e_crlc", "e_cparhdr", "e_minalloc", "e_maxalloc", "e_ss", "e_sp", "e_csum", "e_ip", "e_cs", "e_lfarlc", "e_ovno", "e_res", "e_oemid", "e_oeminfo", "e_res2", "e_lfanew" };
        public string[] DOS_HEADER_OTH = new string[] { "DOS可执行文件标记'MZ'", "", "", "", "", "", "", "", "", "", "DOS代码入口IP", "DOS代码入口CS", "", "", "", "", "", "", "指向PE文件头" };
        public int[] DOS_HEADER_LEN = new int[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 8, 2, 2, 20, 4 };
        public _IMAGE_DOS_HEADER DOS_HEADER = new _IMAGE_DOS_HEADER();

        [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
        public class _IMAGE_DOS_HEADER {            // DOS .EXE header
            public WORD        e_magic;                     // Magic number
            public WORD        e_cblp;                      // Bytes on last page of file
            public WORD        e_cp;                        // Pages in file
            public WORD        e_crlc;                      // Relocations
            public WORD        e_cparhdr;                   // Size of header in paragraphs
            public WORD        e_minalloc;                  // Minimum extra paragraphs needed
            public WORD        e_maxalloc;                  // Maximum extra paragraphs needed
            public WORD        e_ss;                        // Initial (relative) SS value
            public WORD        e_sp;                        // Initial SP value
            public WORD        e_csum;                      // Checksum
            public WORD        e_ip;                        // Initial IP value
            public WORD        e_cs;                        // Initial (relative) CS value
            public WORD        e_lfarlc;                    // File address of relocation table
            public WORD        e_ovno;                      // Overlay number
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
            public WORD[]      e_res;// = new WORD[4];         // Reserved words
            public WORD        e_oemid;                     // OEM identifier (for e_oeminfo)
            public WORD        e_oeminfo;                   // OEM information; e_oemid specific
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
            public WORD[]      e_res2;// = new WORD[10];       // Reserved words
            public DWORD       e_lfanew;                    // File address of new exe header
        }

        public string[] FILE_HEADER_TXT = new string[] { "Machine", "NumberOfSections", "TimeDateStamp", "PointerToSymbolTable", "NumberOfSymbols", "SizeOfOptionalHeader", "Characteristics" };
        public string[] FILE_HEADER_OTH = new string[] { "运行平台", "文件区块数目", "文件创建日期和时间", "指向符号表(用于调试)", "符号表中符号个数(用于调试)", "IMAGE_OPTIONAL_HEADER32结构大小", "文件属性" };
        public int[] FILE_HEADER_LEN = new int[] { 2, 2, 4, 4, 4, 2, 2 };
        public _IMAGE_FILE_HEADER FILE_HEADER = new _IMAGE_FILE_HEADER();
        public DWORD FILE_HEADER_START;
        [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
        public class _IMAGE_FILE_HEADER
        {
            public WORD    Machine;
            public WORD    NumberOfSections;
            public DWORD   TimeDateStamp;
            public DWORD   PointerToSymbolTable;
            public DWORD   NumberOfSymbols;
            public WORD    SizeOfOptionalHeader;
            public WORD    Characteristics;
        }

        public string[] OPTIONAL_HEADER_TXT = new string[] { "Magic", "MajorLinkerVersion", "MinorLinkerVersion", "SizeOfCode", "SizeOfInitializedData", "SizeOfUninitializedData", "AddressOfEntryPoint", "BaseOfCode", "BaseOfData", "ImageBase", "SectionAlignment", "FileAlignment", "MajorOperatingSystemVersion", "MinorOperatingSystemVersion", "MajorImageVersion", "MinorImageVersion", "MajorSubsystemVersion", "MinorSubsystemVersion", "Win32VersionValue", "SizeOfImage", "SizeOfHeaders", "CheckSum", "Subsystem", "DllCharacteristics", "SizeOfStackReserve", "SizeOfStackCommit", "SizeOfHeapReserve", "SizeOfHeapCommit", "LoaderFlags", "NumberOfRvaAndSizes" };
        public string[] OPTIONAL_HEADER_OTH = new string[] { "标识字", "链接器主版本号", "链接器次版本号", "所有含有代码区块的总大小", "所有初始化数据区块总大小", "所有未初始化数据区块总大小", "程序入口RAV", "代码区块起始RAV", "数据区块起始RAV", "程序默认装入基地址", "内存中区块的对齐值", "文件中区块的对齐值", "操作系统主版本号", "操作系统次版本号", "用户自定义主版本号", "用户自定义此版本号", "所需子系统主版本号", "所需子系统次版本号", "保留，通常被设为0", "映像装入内存后的总尺寸", "DOS头、PE头、区块表总大小", "映像校验和", "文件子系统", "显示DLL特性的旗标", "初始化堆栈大小", "初始化实际提交堆栈大小", "初始化保留堆栈大小", "初始化实际保留堆栈大小", "与调试相关，默认值为0", "数据目录表的项数" };
        public int[] OPTIONAL_HEADER_LEN = new int[] { 2, 1, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 2, 2, 4, 4, 4, 4, 4, 4, 16 };
        public _IMAGE_OPTIONAL_HEADER OPTIONAL_HEADER = new _IMAGE_OPTIONAL_HEADER();
        public DWORD OPTIONAL_HEADER_START;
        [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
        public class _IMAGE_OPTIONAL_HEADER {
            // Standard fields.
            public WORD  Magic;
            public BYTE  MajorLinkerVersion;
            public BYTE  MinorLinkerVersion;
            public DWORD SizeOfCode;
            public DWORD SizeOfInitializedData;
            public DWORD SizeOfUninitializedData;
            public DWORD AddressOfEntryPoint;
            public DWORD BaseOfCode;
            public DWORD BaseOfData;
            // NT additional fields.
            public DWORD ImageBase;
            public DWORD SectionAlignment;
            public DWORD FileAlignment;
            public WORD  MajorOperatingSystemVersion;
            public WORD  MinorOperatingSystemVersion;
            public WORD  MajorImageVersion;
            public WORD  MinorImageVersion;
            public WORD  MajorSubsystemVersion;
            public WORD  MinorSubsystemVersion;
            public DWORD Win32VersionValue;
            public DWORD SizeOfImage;
            public DWORD SizeOfHeaders;
            public DWORD CheckSum;
            public WORD  Subsystem;
            public WORD  DllCharacteristics;
            public DWORD SizeOfStackReserve;
            public DWORD SizeOfStackCommit;
            public DWORD SizeOfHeapReserve;
            public DWORD SizeOfHeapCommit;
            public DWORD LoaderFlags;
            public DWORD NumberOfRvaAndSizes;
            //public IMAGE_DATA_DIRECTORY[] DataDirectory = new IMAGE_DATA_DIRECTORY[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
        }

        //数据目录表
        public const int IMAGE_DIRECTORY_ENTRY_EXPORT         =  0;   // Export Directory
        public const int IMAGE_DIRECTORY_ENTRY_IMPORT         =  1;   // Import Directory
        public const int IMAGE_DIRECTORY_ENTRY_RESOURCE       =  2;   // Resource Directory
        public const int IMAGE_DIRECTORY_ENTRY_EXCEPTION      =  3;   // Exception Directory
        public const int IMAGE_DIRECTORY_ENTRY_SECURITY       =  4;   // Security Directory
        public const int IMAGE_DIRECTORY_ENTRY_BASERELOC      =  5;   // Base Relocation Table
        public const int IMAGE_DIRECTORY_ENTRY_DEBUG          =  6;   // Debug Directory
        //      IMAGE_DIRECTORY_ENTRY_COPYRIGHT       7   // (X86 usage)
        public const int IMAGE_DIRECTORY_ENTRY_ARCHITECTURE   =  7;   // Architecture Specific Data
        public const int IMAGE_DIRECTORY_ENTRY_GLOBALPTR      =  8;   // RVA of GP
        public const int IMAGE_DIRECTORY_ENTRY_TLS            =  9;   // TLS Directory
        public const int IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG    = 10;   // Load Configuration Directory
        public const int IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT   = 11;   // Bound Import Directory in headers
        public const int IMAGE_DIRECTORY_ENTRY_IAT            = 12;   // Import Address Table
        public const int IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT   = 13;   // Delay Load Import Descriptors
        public const int IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR = 14;   // COM Runtime descriptor
        
        public string[] DATA_DIRECTORY_TIT = new string[] { "Export Directory", "Import Directory", "Resource Directory", "Exception Directory", "Security Directory", "Base Relocation Table", "Debug Directory", "Architecture Specific Data", "RVA of GP", "TLS Directory", "Load Configuration Directory", "Bound Import Directory in headers", "Import Address Table", "Delay Load Import Descriptors", "COM Runtime descriptor" };
        public string[] DATA_DIRECTORY_TXT = new string[] { "VirtualAddress", "Size" };
        public string[] DATA_DIRECTORY_OTH = new string[] { "数据块起始RVA", "数据块长度" };
        public int[] DATA_DIRECTORY_LEN = new int[] { 4, 4 };
        public DWORD DATA_DIRECTORY_START;                                                     //数据目录表起始位置
        public IMAGE_DATA_DIRECTORY[] DATA_DIRECTORY = new IMAGE_DATA_DIRECTORY[16];
        [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
        public class IMAGE_DATA_DIRECTORY
        {
            public DWORD   VirtualAddress;                                                      //数据块的起始RVA
            public DWORD   Size;                                                                //数据块的长度
        }
        
        //区块
        public const int IMAGE_SIZEOF_SHORT_NAME             = 8;
        public string[] SECTION_HEADER_TXT = new string[] { "Name", /*"PhysicalAddress",*/"VirtualSize","VirtualAddress", "SizeOfRawData", "PointerToRawData", "PointerToRelocations", "PointerToLinenumbers", "NumberOfRelocations", "NumberOfLinenumbers", "Characteristics" };
        public string[] SECTION_HEADER_OTH = new string[] { "块名", "区块尺寸", "区块RVA地址", "在文件中对齐后的尺寸", "在文件中的偏移", "在obj文件中使用，重定位的偏移", "行号表的偏移（供调试用）", "在obj文件中使用，重定位项数目", "行号表中行号的数据", "区块的属性" };
        public int[] SECTION_HEADER_LEN = new int[] { 8,/* 4,*/ 4, 4, 4, 4, 4, 4, 2, 2, 4 };
        public DWORD SECTION_HEADER_START;                                                     //区块表起始位置
        public _IMAGE_SECTION_HEADER[] SECTION_HEADER;
        [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
        public class _IMAGE_SECTION_HEADER {
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
            public BYTE[] Name = new BYTE[IMAGE_SIZEOF_SHORT_NAME];
            //union {
            //public DWORD   PhysicalAddress;
            public DWORD   VirtualSize;
            //} 
            public DWORD   VirtualAddress;
            public DWORD   SizeOfRawData;
            public DWORD   PointerToRawData;
            public DWORD   PointerToRelocations;
            public DWORD   PointerToLinenumbers;
            public WORD    NumberOfRelocations;
            public WORD    NumberOfLinenumbers;
            public DWORD   Characteristics;
        }

        //输入表
        public string[] IMPORT_DESCRIPTOR_TXT = new string[] { /*"Characteristics",*/"OriginalFirstThunk", "TimeDateStamp", "ForwarderChain", "Name", "FirstThunk" };
        public int[] IMPORT_DESCRIPTOR_LEN = new int[] { 4, 4, 4, 4, 4 };
        public DWORD IMPORT_DESCRIPTOR_START;
        public _IMAGE_IMPORT_DESCRIPTOR[] IMPORT_DESCRIPTOR;
        [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
        public class _IMAGE_IMPORT_DESCRIPTOR {
            //union {
            //public DWORD   Characteristics;                 // 0 for terminating null import descriptor
            public DWORD   OriginalFirstThunk;            // RVA to original unbound IAT (PIMAGE_THUNK_DATA)
            //};
            public DWORD   TimeDateStamp;                   // 0 if not bound,
                                                            // -1 if bound, and real date\time stamp
                                                            //     in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT (new BIND)
                                                            // O.W. date/time stamp of DLL bound to (Old BIND)

            public DWORD   ForwarderChain;                  // -1 if no forwarders
            public DWORD   Name;
            public DWORD   FirstThunk;                      // RVA to IAT (if bound this IAT has actual addresses)
        }

        [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
        public class _IMAGE_THUNK_DATA32
        {
            //union ul
            //public DWORD ForwarderString;      // PBYTE 
            //public DWORD Function;             // PDWORD
            //public DWORD Ordinal;
            public DWORD AddressOfData;        // PIMAGE_IMPORT_BY_NAME
            //ends
        }

        [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
        public class _IMAGE_IMPORT_BY_NAME
        {
            public WORD Hint;
            public BYTE Name;
        }

        //输出表
        public DWORD EXPORT_DIRECTORY_START;
        public _IMAGE_EXPORT_DIRECTORY EXPORT_DIRECTORY = new _IMAGE_EXPORT_DIRECTORY();
        [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
        public class _IMAGE_EXPORT_DIRECTORY {
            public DWORD   Characteristics;
            public DWORD   TimeDateStamp;
            public WORD    MajorVersion;
            public WORD    MinorVersion;
            public DWORD   Name;
            public DWORD   Base;
            public DWORD   NumberOfFunctions;
            public DWORD   NumberOfNames;
            public DWORD   AddressOfFunctions;     // RVA from base of image
            public DWORD   AddressOfNames;         // RVA from base of image
            public DWORD   AddressOfNameOrdinals;  // RVA from base of image
        }

        //基址重定位
        [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
        public class _IMAGE_BASE_RELOCATION {
            public DWORD   VirtualAddress;
            public DWORD   SizeOfBlock;
            //  WORD    TypeOffset[1];
        }

        //资源
        public string[] RESOURCE_DIRECTORY_CAPTION = new string[]{"","光标(Cursor)","位图(Bitmap)","图标(Icon)","菜单(Menu)","对话框(Dialog)","字符串(String)","字体目录(Font Directory)",
            "字体(Font)","加速键(Accelerators)","未格式资源(Unformatted)","消息表(MessageTable)","光标组(Group Cursor)","","图标组(Group Icon)","","版本信息(Version Information)"};
        public DWORD RESOURCE_DIRECTORY_START;
        public _IMAGE_RESOURCE_DIRECTORY RESOURCE_DIRECTORY = new _IMAGE_RESOURCE_DIRECTORY();
        [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
        public class _IMAGE_RESOURCE_DIRECTORY {
            public DWORD   Characteristics;
            public DWORD   TimeDateStamp;
            public WORD    MajorVersion;
            public WORD    MinorVersion;
            public WORD    NumberOfNamedEntries;
            public WORD    NumberOfIdEntries;
            //  IMAGE_RESOURCE_DIRECTORY_ENTRY DirectoryEntries[];
        }

        public _IMAGE_RESOURCE_DIRECTORY_ENTRY RESOURCE_DIRECTORY_ENTRY = new _IMAGE_RESOURCE_DIRECTORY_ENTRY();
        [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
        public class _IMAGE_RESOURCE_DIRECTORY_ENTRY {
            //union {
            //    struct {
            //        DWORD NameOffset:31;
            //        DWORD NameIsString:1;
            //    };
                public DWORD   Name;   //最高位为0时，作为ID使用；为1时指向 _IMAGE_RESOURCE_DIR_STRING_U
            //    WORD    Id;
            //};
            //union {
                public DWORD   OffsetToData;
            //    struct {
            //        DWORD   OffsetToDirectory:31;
            //        DWORD   DataIsDirectory:1;
            //    };
            //};
        }

        public _IMAGE_RESOURCE_DIR_STRING_U RESOURCE_DIR_STRING_U = new _IMAGE_RESOURCE_DIR_STRING_U();
        [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
        public class _IMAGE_RESOURCE_DIR_STRING_U {
            public WORD    Length;
            public WCHAR   NameString;
        }

        [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
        public class _IMAGE_RESOURCE_DATA_ENTRY {
            public DWORD   OffsetToData;
            public DWORD   Size;
            public DWORD   CodePage;
            public DWORD   Reserved;
        }
    }
}
